#ifndef __MY_DATA__
#define __MY_DATA__

#include "Util.hpp"
#include "Log.hpp"
#include <cstdlib>
#include <mutex>
#include <mysql/mysql.h>

namespace vedio_sharing {
    // 数据库连接配置常量
    const std::string DB_HOST = "127.0.0.1";
    const std::string DB_USER = "root";
    const std::string DB_PASS = "20041010@@Wtq";
    const std::string DB_NAME = "video_system";

    // 初始化 MySQL 连接
    // 成功返回 MYSQL 指针，失败返回 NULL
    MYSQL* MysqlInit() {
        MYSQL* mysql = mysql_init(nullptr);
        if (mysql == nullptr) {
            ERR_LOG("Init mysql instance failed!\n");
            return nullptr;
        }
        if (mysql_real_connect(mysql, DB_HOST.c_str(), DB_USER.c_str(), DB_PASS.c_str(), DB_NAME.c_str(), 0, nullptr, 0) == nullptr) {
            ERR_LOG("Connect mysql server failed! Error: %s\n", mysql_error(mysql));
            mysql_close(mysql);
            return nullptr;
        }
        if (mysql_set_character_set(mysql, "utf8") != 0) {
            ERR_LOG("Set mysql character set to utf8 failed! Error: %s\n", mysql_error(mysql));
        }
        return mysql;
    }

    // 销毁 MySQL 连接
    // mysql：要销毁的 MYSQL 指针
    void MysqlDestroy(MYSQL* mysql) {
        if (mysql != nullptr) {
            mysql_close(mysql);
        }
    }

    // 执行 MySQL 查询
    // mysql：MySQL 连接指针
    // sql：要执行的 SQL 语句
    bool MysqlQuery(MYSQL* mysql, const std::string& sql) {
        int ret = mysql_query(mysql, sql.c_str());
        if (ret != 0) {
            ERR_LOG("SQL query failed: %s\n", sql.c_str());
            ERR_LOG("Error message: %s\n", mysql_error(mysql));
            return false;
        }
        return true;
    }

    // 视频数据表操作类
    class TableVideo {
    private:
        MYSQL* mysql_;  // MySQL 连接指针
        std::mutex mutex_;  // 互斥锁，用于线程安全

    public:
        // 构造函数，初始化 MySQL 连接
        TableVideo() {
            mysql_ = MysqlInit();
            if (mysql_ == nullptr) {
                ERR_LOG("MysqlInit failed!\n");
                exit(-1);
            }
        }

        // 析构函数，销毁 MySQL 连接
        ~TableVideo() {
            MysqlDestroy(mysql_);
        }

        // 插入视频记录
        // video：包含视频信息的 Json::Value 对象
        bool Insert(const Json::Value& video) {
            if (video["name"].asString().empty()) {
                ERR_LOG("Cannot find video name!\n");
                return false;
            }
            std::string sql;
            sql.resize(4096 + video["info"].asString().size());  // 防止简介过长
            const std::string insert_sql = "INSERT INTO tb_video VALUES(null, '%s', '%s', '%s', '%s');";
            std::snprintf(&sql[0], sql.size(), insert_sql.c_str(),
                          video["name"].asCString(),
                          video["info"].asCString(),
                          video["video"].asCString(),
                          video["image"].asCString());
            return MysqlQuery(mysql_, sql);
        }

        // 更新视频记录
        // video_id：要更新的视频记录的 ID
        // video：包含新视频信息的 Json::Value 对象
        bool Update(int video_id, const Json::Value& video) {
            std::string sql;
            sql.resize(4096 + video["info"].asString().size());  // 防止简介过长
            const std::string update_sql = "UPDATE tb_video SET name='%s', info='%s' WHERE id=%d;";
            std::snprintf(&sql[0], sql.size(), update_sql.c_str(),
                          video["name"].asCString(),
                          video["info"].asCString(),
                          video_id);
            return MysqlQuery(mysql_, sql);
        }

        // 删除视频记录
        // video_id：要删除的视频记录的 ID
        bool Delete(int video_id) {
            const std::string delete_sql = "DELETE FROM tb_video WHERE id=%d;";
            char sql[1024] = {0};
            std::snprintf(sql, sizeof(sql), delete_sql.c_str(), video_id);
            return MysqlQuery(mysql_, sql);
        }

        // 查询所有视频记录
        // videos：用于存储查询结果的 Json::Value 对象指针
        bool SelectAll(Json::Value* videos) {
            const std::string select_all_sql = "SELECT * FROM tb_video;";
			MYSQL_RES* res = nullptr;
			{
				std::lock_guard<std::mutex> lock(mutex_);
				if (!MysqlQuery(mysql_, select_all_sql)) {
					ERR_LOG("MysqlQuery execute failed!\n");
					return false;
				}
				res = mysql_store_result(mysql_);
				if (res == nullptr) {
					ERR_LOG("mysql store result failed! Error: %s\n", mysql_error(mysql_));
					return false;
				}
			}
            int num_rows = mysql_num_rows(res);
            for (int i = 0; i < num_rows; ++i) {
                MYSQL_ROW row = mysql_fetch_row(res);
                Json::Value video;
                video["id"] = std::atoi(row[0]);
                video["name"] = row[1];
                video["info"] = row[2];
                video["video"] = row[3];
                video["image"] = row[4];
                videos->append(video);
            }
            mysql_free_result(res);
            return true;
        }

        // 查询单个视频记录
        // video_id：要查询的视频记录的 ID
        // video：用于存储查询结果的 Json::Value 对象指针
        bool SelectOne(int video_id, Json::Value* video) {
            const std::string select_one_sql = "SELECT * FROM tb_video WHERE id=%d;";
            char sql[1024] = {0};
			MYSQL_RES* res = nullptr;
            std::snprintf(sql, sizeof(sql), select_one_sql.c_str(), video_id);
			{
				std::lock_guard<std::mutex> lock(mutex_);
				if (!MysqlQuery(mysql_, sql)) {
					ERR_LOG("MysqlQuery execute failed!\n");
					return false;
				}
				res = mysql_store_result(mysql_);
				if (res == nullptr) {
					ERR_LOG("mysql store result failed! Error: %s\n", mysql_error(mysql_));
					return false;
				}
				int num_rows = mysql_num_rows(res);
				if (num_rows != 1) {
					ERR_LOG("mysql_num_rows have no data or more than one record!\n");
					mysql_free_result(res);
					return false;
				}
			}
            
            MYSQL_ROW row = mysql_fetch_row(res);
            (*video)["id"] = video_id;
            (*video)["name"] = row[1];
            (*video)["info"] = row[2];
            (*video)["video"] = row[3];
            (*video)["image"] = row[4];
            mysql_free_result(res);
            return true;
        }

        // 模糊查询视频记录
        // key：模糊查询的关键字
        // videos：用于存储查询结果的 Json::Value 对象指针
        bool SelectLike(const std::string& key, Json::Value* videos) {
            const std::string select_like_sql = "SELECT * FROM tb_video WHERE name LIKE '%%%s%%';";
            char sql[1024] = {0};
			MYSQL_RES* res = nullptr;
            std::snprintf(sql, sizeof(sql), select_like_sql.c_str(), key.c_str());
			{
				std::lock_guard<std::mutex> lock(mutex_); 
				if (!MysqlQuery(mysql_, sql)) {
					ERR_LOG("MysqlQuery execute failed!\n");
					return false;
				}
				res = mysql_store_result(mysql_);
				if (res == nullptr) {
					ERR_LOG("mysql store result failed! Error: %s\n", mysql_error(mysql_));
					return false;
				}
			}
            int num_rows = mysql_num_rows(res);
            for (int i = 0; i < num_rows; ++i) {
                MYSQL_ROW row = mysql_fetch_row(res);
                Json::Value video;
                video["id"] = std::atoi(row[0]);
                video["name"] = row[1];
                video["info"] = row[2];
                video["video"] = row[3];
                video["image"] = row[4];
                videos->append(video);
            }
            mysql_free_result(res);
            return true;
        }
    };

}

#endif